package com.ihealthway.all.groupbuy.services;

import com.ihealthway.all.groupbuy.vo.Goods;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * Goods service
 *
 * @author 凡梦星尘(elkan1788@gmail.com)
 */
@IocBean(fields = {"dao"})
public class GoodsService extends BaseService<Goods> {

    private static final Log logger = Logs.get();

    @Inject
    private ImageLibraryService imgLibService;

    public Goods getGoodsPrice(Integer goodsId) {
        Goods goods = null;
        if (goodsId != null || goodsId.intValue() > 0) {
            Sql sql = Sqls.create("SELECT goods_name,price FROM gb_goods WHERE goods_id=@goodsId AND data_status='0'");
            sql.setParam("goodsId", goodsId);
            sql.setCallback(Sqls.callback.entities());
            sql.setEntity(dao().getEntity(Goods.class));
            try {
                dao().execute(sql);
                List<Goods> data = sql.getList(Goods.class);
                if (data!=null && !data.isEmpty()) {
                    goods = data.get(0);
                    logger.infof("Find good price: %s-%d", goods.getGoodsName(), goods.getPrice());
                }
            } catch (Exception e) {
                logger.error("Check user submit goodsId fail!!!", e);
            }
        }

        return goods;
    }

    public boolean checkGoodsLimit(Integer goodsId) {
        boolean flag = false;
        String sqlStmt = "SELECT limit_num <> sales AS num FROM gb_goods WHERE goods_id = "+goodsId;
        Sql sql = Sqls.create(sqlStmt);
        sql.setCallback(new SqlCallback() {
            @Override
            public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
                while (rs.next()) {
                   return rs.getInt("num");
                }

                return new Integer(0);
            }
        });
        try {
            dao().execute(sql);
            Integer result  = sql.getObject(Integer.class);
            flag = (result.intValue() > 0);
        } catch (Exception e) {
            logger.error("Check goods limit number fail!!!", e);
        }
        return flag;
    }


    public void increaseGoodsSale(Integer goodsId) {
        Sql sql = Sqls.create("UPDATE gb_goods SET sales = sales+1 WHERE goods_id = @goodsId");
        sql.setParam("goodsId", goodsId);
        try {
            dao().execute(sql);
        } catch (Exception e) {
            logger.error("Update goods sale count fail!!!", e);
        }
    }

    public Goods getGoodsInfoOnFront(Integer goodsId) {
        List<Goods> goodsList = dao().query(Goods.class, Cnd.where("goods_id", "=", goodsId.intValue()));
        return goodsList.get(0);
    }

    public List<Goods> getGoodsInfoOnFront(String goodsName) {
        Criteria cri  = Cnd.cri();
        cri.where().andLike("goods_name", goodsName);
        List<Goods> goodsList = dao().query(Goods.class, cri);
        return goodsList;
    }

    public List<Goods> getGoodsListIOnFront(Integer companyId, Integer goodsType, String goodsName) {
        Sql sql = Sqls.create("SELECT gs.*,img.img_url AS imgUrl FROM gb_goods AS gs " +
                "LEFT JOIN (SELECT MIN(img_url) AS img_url,MAX(img_id) AS img_id,goods_id FROM gb_images_library " +
                "WHERE goods_id IS NOT NULL GROUP BY goods_id) AS img ON img.goods_id = gs.goods_id " +
                "$condition");

        Criteria cri = Cnd.cri();
        cri.where().andEquals("gs.data_status", 0);
        if (companyId!=null && companyId.intValue()!=-1) {
            cri.where().andEquals("gs.c_id", companyId.intValue());
        }
        if (goodsType!=null && goodsType.intValue()!=-1) {
            cri.where().andEquals("gs.goods_type", companyId.intValue());
        }
        if (Strings.isNotBlank(goodsName)) {
            cri.where().andLike("gs.goods_name", goodsName);
        }
        cri.getOrderBy().desc("gs.create_time");

        sql.setCondition(cri);
        sql.setCallback(new SqlCallback() {
            @Override
            public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
                List<Goods> goodsList = new ArrayList<>();
                while (rs.next()) {
                    Goods goods = getEntity().getObject(rs, null, "gs.");
                    String imgUrl = rs.getString("imgUrl");
                    goods.setImgUrl(imgUrl);

                    goodsList.add(goods);
                }
                return goodsList;
            }
        });
        sql.setPager(dao().createPager(1, 30));

        List<Goods> goodsList = dao().execute(sql).getList(Goods.class);
        return goodsList;
    }

    public Map<String, Integer> sumGoods() {
        String sqlStmt = "SELECT COUNT(goods_id) AS total, " +
                "SUM(CASE WHEN goods_type = 1 THEN 1 ELSE 0 END) AS a, " +
                "SUM(CASE WHEN data_status=0 THEN 1 ELSE 0 END ) AS sale " +
                "FROM gb_goods WHERE data_status <> '1'";

        Map<String, Integer> sumData = (Map<String, Integer>) dao().execute(Sqls.create(sqlStmt).setCallback(new GoodsSumCallback())).getResult();

        return sumData;
    }

    public boolean add(Goods goods) {

        boolean add = false;

        goods.setCreateTime(new Date());
        goods.setDataStatus("0");
        goods.setSales(0);

        try {
            Goods insertTemp = _insert(goods);
            add = insertTemp != null;
            Integer goodsId = insertTemp.getGoodsId();
            if (goodsId!=null) {
                imgLibService.updateGoodsImg(goods.getImgUrl(), goodsId);
            }
        } catch (Exception e) {
            logger.error(goods);
            logger.error("Insert new goods info failed!!!", e);
        }

        return add;
    }

    public boolean update(Goods goods) {

        boolean update = false;

        goods.setUpdateTime(new Date());
        try {
            int effectRows = _updateIgnoreNull(goods);
            update = effectRows != 0;
            if (update && Strings.isNotBlank(goods.getImgUrl())) {
                imgLibService.updateGoodsImg(goods.getImgUrl(), goods.getGoodsId());
            }
        } catch (Exception e) {
            logger.error(goods);
            logger.error("Update goods info failed!!!", e);
        }

        return update;
    }

    public Map<String, Object>  getData(int page, int rows, String goodsName, int companyId) {

        Map<String, Object> result = new HashMap<>();

        Criteria cri = Cnd.cri();

        String sqlStmt = "SELECT gs.*,com.c_name AS companyName,img.imgIds FROM gb_goods AS gs " +
                "LEFT JOIN gb_company AS com ON com.c_id = gs.c_id " +
                "LEFT JOIN (SELECT GROUP_CONCAT(img_id) AS imgIds,goods_id FROM gb_images_library " +
                "WHERE goods_id IS NOT NULL GROUP BY goods_id) AS img ON img.goods_id = gs.goods_id " +
                "$condition";
        cri.where().andNotEquals("gs.data_status", "1");
        cri.getOrderBy().desc("create_time");

        if (Strings.isNotBlank(goodsName)) {
            String[] goodsNameCnd = goodsName.split(",");
            cri.where().andLike("gs.goods_name", goodsNameCnd[1]);
            if (!Strings.equalsIgnoreCase(goodsNameCnd[0], "all")) {
                cri.where().andEquals("gs.goods_type", goodsNameCnd[0]);
            }
        }
        if (companyId!=0) {
            cri.where().andEquals("gs.c_id", companyId);
        }

        result.putAll(easyuiDGPagerWithFetch(sqlStmt, page, rows, cri, new GoodsPagerCallback()));

        return result;
    }

    private class GoodsPagerCallback implements SqlCallback {

        private List<Goods> goodsList = new ArrayList<>();

        @Override
        public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {

            while (rs.next()) {
                Goods goods = getEntity().getObject(rs, null, "gs.");
                String nickName = rs.getString("companyName");
                goods.setCompanyName(nickName);
                String imgIds = rs.getString("imgIds");
                goods.setImgUrl(imgIds);

                goodsList.add(goods);
            }

            return goodsList;
        }
    }


    private class GoodsSumCallback implements SqlCallback {

        private Map<String, Integer> sumMap = new HashMap<>();

        @Override
        public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {

            while (rs.next()) {
                int total = rs.getInt("total");
                int a = rs.getInt("a");
                int b = total - a;
                int sale = rs.getInt("sale");
                int unSale = total - sale;
                sumMap.put("total", total);
                sumMap.put("a", a);
                sumMap.put("b", b);
                sumMap.put("sale", sale);
                sumMap.put("unSale", unSale);
            }

            return sumMap;
        }
    }

}
